/*
 * cm_math.h
 *
 *  Created on: Sep 18, 2015
 *      Author: song
 */

#ifndef INCLUDE_CM_CM_MATH_H_
#define INCLUDE_CM_CM_MATH_H_

#include <assert.h>

/*
 * @brief   计算底为base，n的对数，换底公式
 */
static inline double cm_log(double base, double n)
{
    assert(base > 0 && base != 1 && n > 0);
    return (log(n) / log(base));
}

/*
 * @brief   快速计算以2为底，x的对数， 依赖浮点数的存储方式，IEEE规格化浮点数
 */
static inline int fast_log2(int x)
{
    float fx;
    unsigned long ix, exp;

    fx = (float) x;
    ix = *(unsigned long*) &fx;
    exp = (ix >> 23) & 0xFF;

    return exp - 127;
}

/*
 * @brief   判断n是否是2的幂次
 * @return  bool
 */
static inline int is_power_of_2(int n)
{
    if (n <= 0)
        return 0;

    return ((n & (n - 1)) == 0);
}

/*
 * @brief   计算大于等于数n，是2的幂次且最小的一个数
 */
static inline int min_power_of_2_g(int n)
{
    // |---若干个0---|-第x位为1-|----任意---|
    n |= n >> 1; // 首位x及x后一位为1
    n |= n >> 2; // 从x起4位为1
    n |= n >> 4; // 8
    n |= n >> 8; // 16
    n |= n >> 16; // 32

    // 至此x后面的位全部变成1

    return (n + 1);
}

/*
 * @brief   同上，但是检查了合法性以及当n已经是2的幂次则直接返回了
 */
static inline int min_power_of_2_eg(int n)
{
    if (n <= 0)
        return 1;

    if (is_power_of_2(n))
        return n;

    return min_power_of_2_g(n);
}

#endif /* INCLUDE_CM_CM_MATH_H_ */
